ImageGear Professional for Linux
Sample Run Ends Code

The following is a sample function that decompresses a run ends raster into uncompressed unpacked (1 byte per pixel) format. It's designed to work with the data you would get from IG_runs_row_get().

 
Copy Code
// runsToUnpacked: Decompresses a run ends raster to unpacked format.
//   nWidth - width of image in pixels
//   lpRuns - pointer to input buffer containing run ends data
//   lpPixels - pointer to output buffer to receive unpacked pixel data
void runsToUnpacked(AT_DIMENSION nWidth, LPAT_RUN lpRuns, LPAT_PIXEL lpPixels)
{
        // Starting color is white
        AT_PIXEL outputPixColor = 1;
        // Loop through runs
        AT_INT outputPixPos = 0;
        while (1)
        {
                // Find out when the current run ends
                AT_RUN runEnd = *lpRuns++;
                // Fill in pixels for this run
                while (outputPixPos < runEnd)
                        lpPixels[outputPixPos++] = outputPixColor;
                // Have we reached the end?
                if (outputPixPos >= nWidth)
                        break;
                // Switch colors for next run
                outputPixColor = !outputPixColor;
        }
}

The following is a more minimalist view of the same function:

 
Copy Code
void runsToUnpacked(AT_DIMENSION w, LPAT_RUN lpRuns, LPAT_PIXEL lpPixels)
{
        AT_PIXEL c = 1;
        AT_INT x = 0;
        while (1)
        {
                AT_RUN r = *lpRuns++;
                while (x < r)
                        lpPixels[x++] = c;
                if (x >= w)
                        break;
                c = !c;
        }
}

The following is a more complex function that creates a 90-degree rotated copy of an image. It operates entirely on run ends data without ever decompressing the data. Note that this is only sample code. This does not represent how ImageGear works internally. Also, error handling is omitted.

 
Copy Code
// Returns a 90-degree rotated copy of the source image
HIGEAR rotate90(HIGEAR hImageSrc)
{
        HIGEAR hImageDst = NULL;
        HIGDIBINFO hDIB;
        AT_INT d[1] = { 1 };
        AT_DIMENSION srcWidth, srcHeight, dstWidth, dstHeight;
        AT_PIXPOS x, y;
        // Get info about source image
        IG_image_dimensions_get(hImageSrc, &srcWidth, &srcHeight, NULL);
        // Create destination image
        dstWidth = srcHeight;
        dstHeight = srcWidth;
        IG_DIB_info_create(&hDIB, dstWidth, dstHeight, IG_COLOR_SPACE_ID_I, 1, d);
        IG_DIB_palette_alloc(hDIB);
        IG_image_create(hDIB, &hImageDst);
IG_DIB_info_delete(hDIB);
        AT_RGB rgb = { 255, 255, 255 };
        IG_palette_entry_set(hImageDst, &rgb, 1);
        // Make a list of source raster pointers
        LPAT_RUN *lpSrcRasters = NULL;
        lpSrcRasters = (LPAT_RUN *) malloc(sizeof(LPAT_RUN) * srcHeight);
        // Make a list of current colors for source runs
        LPAT_BYTE lpSrcRunColors = NULL;
        lpSrcRunColors = (LPAT_BYTE) malloc(sizeof(AT_BYTE) * srcHeight);
        // Populate the lists
        for (y = 0; y < srcHeight; y++)
        {
                AT_RUN runCount;
                IG_runs_row_get(hImageSrc, y, &runCount, &lpSrcRasters[y]);
                if (*lpSrcRasters[y])
                        lpSrcRunColors[y] = 1;
                else
                {
                        lpSrcRunColors[y] = 0;
                        lpSrcRasters[y]++;
                }
        }
        // Allocate a raster large enough to store worst-case input data
        LPAT_RUN lpDstRaster = (LPAT_RUN) malloc(sizeof(AT_RUN) * (dstWidth + 4));
        // Loop through output rasters
        for (y = 0; y < dstHeight; y++)
        {
                AT_INT nDstRuns = 0;
                AT_BYTE dstRunColor = 1;
                AT_INT srcRasterIndex = srcHeight - 1;
                // If the first source pixel is black, 
// set us up to start with black in the output raster
                if (!lpSrcRunColors[srcRasterIndex])
                {
                        dstRunColor = 0;
                        lpDstRaster[nDstRuns++] = 0;
                }
                // Loop through columns in destination image
                for (x = 0; x < dstWidth; x++)
                {
                        // Check the color of the run in the source raster that 
                        // corresponds to the current column in the destination raster.
                        // Is it the same color as the run we're currently constructing?
                        if (lpSrcRunColors[srcRasterIndex] != dstRunColor)
                        {
                                // If not, then we need to store the run we've been making 
// in the destination raster.
                                lpDstRaster[nDstRuns++] = x;
                                // Alternate the current destination run color
                                dstRunColor = !dstRunColor;
                        }
                        // See if it's time to move on to the next source run for 
// this source raster
                        if (*lpSrcRasters[srcRasterIndex] == y)
                        {
                                lpSrcRasters[srcRasterIndex]++;
                                lpSrcRunColors[srcRasterIndex] = !lpSrcRunColors[srcRasterIndex];
                        }
                        // Move on to the next source raster (go *up* through the source image)
                        srcRasterIndex--;
                }
                // Add the three ending runs to the destination raster
                lpDstRaster[nDstRuns++] = dstWidth;
                lpDstRaster[nDstRuns++] = dstWidth;
                lpDstRaster[nDstRuns++] = dstWidth;
                // Store the destination raster!
                IG_runs_row_set(hImageDst, y, nDstRuns, lpDstRaster);
        }
        // Clean up
        free(lpSrcRasters);
        free(lpSrcRunColors);
        free(lpDstRaster);
        return hImageDst;
}

 

 


©2016. Accusoft Corporation. All Rights Reserved.

Send Feedback